package pl.lodz.p.kipme.dao;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Query;

import pl.lodz.p.kipme.bo.Order;
import pl.lodz.p.kipme.bo.OrderStatus;
import pl.lodz.p.kipme.bo.Product;
import pl.lodz.p.kipme.bo.ProductOrder;
import pl.lodz.p.kipme.entities.OrderEntity;
import pl.lodz.p.kipme.entities.ProductEntity;
import pl.lodz.p.kipme.entities.ProductOrderEntity;
import pl.lodz.p.kipme.exception.BusinessException;
import pl.lodz.p.kipme.util.OrderUtil;
import pl.lodz.p.kipme.util.ProductUtil;

public class OrderDAOImpl extends BasicDaoSupport implements OrderDAO {

	@Override
	public void addOrder(Order order) throws BusinessException {
		Query createQuery = session.createQuery("from OrderEntity where orderId = :orderId");
		createQuery.setParameter("orderId", order.getOrderId());
		Object result = createQuery.uniqueResult();
		if(result != null){
			throw new BusinessException("Order with business id:" + order.getOrderId() + " has been reported previously");
		}
		try{
		session.beginTransaction();
		session.persist(new OrderEntity(order));
		session.getTransaction().commit();
		} catch (Exception e) {
		    session.getTransaction().rollback();
        }
	}

	@Override
	public List<ProductOrder> checkOrderStatus(String orderId) {
		Query query = session.createQuery(
			"select new pl.lodz.p.kipme.bo.ProductOrder(e.numberOfProduct, e.productId, e.productOrderId, " +
			" e.status) from ProductOrderEntity e where e.order.orderId = :orderId");
		query.setParameter("orderId", orderId);
		List<ProductOrder> list = query.list();
		return list;
	}

	@Override
	public List<String> getActiveOrderId() {
		Query createQuery = session.createQuery("select e.orderId from OrderEntity e left join e.products p where p.status != :statusReceived");
		createQuery.setParameter("statusReceived", OrderStatus.RECEIVED);
		@SuppressWarnings("unchecked")
		List<String> list = createQuery.list();
		return list;
	}

	@Override
	public void confirmProductReceive(String productOrderId) throws BusinessException {
		Query createQuery = session.createQuery("from ProductOrderEntity where productOrderId = :productOrderId");
		createQuery.setParameter("productOrderId", productOrderId);
		session.beginTransaction();
		ProductOrderEntity entity = (ProductOrderEntity) createQuery.uniqueResult();
		if(entity == null){
			session.getTransaction().commit();
			throw new BusinessException("ProductOrder with id: " + productOrderId + " does not exists in DB");
		}
		entity.setStatus(OrderStatus.RECEIVED);
		session.update(entity);
		session.getTransaction().commit();
	}

	@Override
	public ProductOrder getProductOrderByBusinessID(String productOrderId) {
		Query query = session
				.createQuery("select new pl.lodz.p.kipme.bo.ProductOrder(e.numberOfProduct, e.productId, e.productOrderId, "
						+ " e.status) from ProductOrderEntity e where e.productOrderId = :productOrderId");
		query.setParameter("productOrderId", productOrderId);
		return (ProductOrder) query.uniqueResult();
	}

	@Override
	public List<Order> getWaitingOrders() {
		Query createQuery = session.createQuery("select e from OrderEntity e left join e.products p where p.status != :statusReceived" +
				" and p.status != :statusCompleted");
		createQuery.setParameter("statusReceived", OrderStatus.RECEIVED);
		createQuery.setParameter("statusCompleted", OrderStatus.COMPLETED);
		@SuppressWarnings("unchecked")
		List<OrderEntity> list = createQuery.list();
		List<Order> returned = new ArrayList<Order>();
		for (OrderEntity orderEntity : list) {
			returned.add(OrderUtil.orderEntity2Order(orderEntity));
		}
		return returned;
	}

	@Override
	public void updateOrder(Order order) throws BusinessException {
		Query createQuery = session.createQuery("from OrderEntity where orderId = :orderId");
		createQuery.setParameter("orderId", order.getOrderId());
		OrderEntity entity = (OrderEntity) createQuery.uniqueResult();
		if(entity == null){
			throw new BusinessException("Order with business id:" + order.getOrderId() + " does not exists in DB");
		}
		for (ProductOrder productOrder : order.getProducts()) {
			updateProductOrder(productOrder);
		}
	}

	private void updateProductOrder(ProductOrder productOrder) throws BusinessException {
		Query createQuery = session.createQuery("from ProductOrderEntity where productOrderId = :productOrderId");
		createQuery.setParameter("productOrderId", productOrder.getProductOrderId());
		session.beginTransaction();
		ProductOrderEntity entity = (ProductOrderEntity) createQuery.uniqueResult();
		if(entity == null){
			session.getTransaction().commit();
			throw new BusinessException("ProductOrder with id: " + productOrder.getProductOrderId() + " does not exists in DB");
		}
		entity.setStatus(productOrder.getStatus());
		session.update(entity);
		session.getTransaction().commit();
	}

}
